#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "rpc_topic.hpp"
#include <thread>

namespace jsonrpc
{
    namespace server
    {
        // 1.注册发现服务端封装
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;
            RegistryServer(int port)
            : _pd_manager(std::make_shared<PD_Manager>())
            , _dispatcher(std::make_shared<jsonrpc::Dispatcher>())
            {
                // 1.向dispatcher注册(服务请求)消息类型对应的回调函数
                auto service_cb = std::bind(&PD_Manager::onServiceRequset, _pd_manager.get(),std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);
                // 2.向dispatcher注册(心跳包)消息类型对应的回调函数
                auto heart_cb = std::bind(&RegistryServer::onHeartbeat, this, std::placeholders::_1);
                _dispatcher->registerHandler<ServiceRequest>(MType::HEARTBEAT, heart_cb);

                // 3.设置服务端的回调函数
                _server = ServerFactory::create(port);
                auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                auto close_cb = std::bind(&RegistryServer::onConnShutdown, this, std::placeholders::_1);
                _server->setMessageCallback(message_cb);
                _server->setCloseCallback(close_cb);

                // 4.开始心跳包检查
                DLOG("开始执行心跳包检查");
                startHeartbeatCheck();
            }

        public:
            void start()
            {
                _server->start();
            }

        private:
            // 响应处理
            void onConnShutdown(BaseConnection::ptr conn)
            {
                _pd_manager->onConnShutdown(conn);
            }

            // 心跳包处理
            void onHeartbeat(const BaseConnection::ptr &conn) 
            {
                // 收到心跳包就更新时间
                DLOG("收到服务提供者的心跳包, 更新它的心跳时间");
                _pd_manager->updateProviderStatus(conn);
            }
        private:
            void startHeartbeatCheck()
            {
                std::thread([this](){
                    while(true)
                    {
                        // 每5s检查一次
                        std::this_thread::sleep_for(std::chrono::seconds(5));
                        checkHeartbeatTimeout();
                    }
                }).detach();
            }

            void checkHeartbeatTimeout()
            {
                auto now = std::chrono::steady_clock::now();
                auto providers = _pd_manager->getAllProviders();
                for(const auto& provider : providers)
                {
                    auto duration = std::chrono::duration_cast<std::chrono::seconds>(now - provider->last_heartbeat_time).count();
                    if(duration > 10)
                    {
                        // 超过20s未收到心跳包, 认为连接断开
                        onConnShutdown(provider->_conn);
                        DLOG("10s未收到服务提供者的心跳包, 认为对端连接断开");
                    }
                }
            }
        private:
            PD_Manager::ptr _pd_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
        // 2.rpc服务端封装
        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            // RpcServer有两套地址信息
            // 1.rpc服务提供端地址信息 -- rpc服务器对外访问地址 (云服务器 -- 监听地址与访问地址不同)
            // 2.注册中心服务端的地址信息 -- 启用服务注册后, 连接注册中心进行服务注册
            RpcServer(const Address& access_addr, bool enableDiscovery = false, const Address& registry_server_addr = Address())
            :_access_addr(access_addr)
            ,_enableRegistry(enableDiscovery)
            ,_router(std::make_shared<RpcRouter>())
            ,_dispatcher(std::make_shared<Dispatcher>())
            {
                // 如果开始注册发现, 创建注册中心
                if(enableDiscovery)
                {
                    _reg_client = std::make_shared<client::RegistryClient>(registry_server_addr.first, registry_server_addr.second);
                    //startHeartBeat(); // 向注册中心发送心跳包
                }
                // 1.向dispatcher注册消息类型对应的回调函数
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<RpcRequest>(MType::REQ_RPC, rpc_cb);
                // 2.设置服务端的回调函数
                _server = ServerFactory::create(access_addr.second);
                auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }

        public:
            // 注册服务方法
            void registerMethod(const ServiceDescribe::ptr &service)
            {
                if(_enableRegistry)
                {
                    // 连接注册中心服务器, 进行服务注册
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
                _router->registerMethod(service);
            }

            void start()
            {
                _server->start();
            }
        private:
            // 发送心跳包
            void startHeartBeat()
            {
                std::thread([this](){
                    while(true)
                    {
                        sendHeartBeat();
                        std::this_thread::sleep_for(std::chrono::seconds(5));// 每5s发送一次心跳包
                    }

                }).detach();
            }

            void sendHeartBeat()
            {
                //DLOG("开始向注册中心发送心跳包");
                auto msg_req = MessageFactory::create<HeartbeatMessage>();
                msg_req->setId(UUID::uuid());
                msg_req->setMType(MType::HEARTBEAT);
                _reg_client->sendHeartbeat(msg_req); // _reg_client向注册中心发送心跳包
            }

        private:
            Address _access_addr;
            bool _enableRegistry;
            client::RegistryClient::ptr _reg_client;
            RpcRouter::ptr _router;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        // 主题服务端封装
        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port)
            : _topic_manager(std::make_shared<TopicManager>())
            , _dispatcher(std::make_shared<jsonrpc::Dispatcher>())
            {
                // 1.向dispatcher注册消息类型对应的回调函数
                auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC, topic_cb);

                // 2.设置服务端的回调函数
                _server = ServerFactory::create(port);
                auto message_cb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                _server->setMessageCallback(message_cb);
                _server->setCloseCallback(close_cb);
            }
        public:
            void start()
            {
                _server->start();
            }
        private:
            void onConnShutdown(BaseConnection::ptr conn)
            {
                _topic_manager->onShutdown(conn);
            }
        private:
            TopicManager::ptr _topic_manager;
            Dispatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }
}